#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""测试运行脚本"""

import os
import sys
import subprocess
import argparse
from pathlib import Path

# Get the project root directory (assuming run_tests.py is in the root)
PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))

def run_command(command, cwd=None):
    """运行命令并返回结果"""
    try:
        result = subprocess.run(
            command,
            shell=True,
            cwd=cwd if cwd else PROJECT_ROOT,  # Set CWD to project root if not specified
            capture_output=True,
            text=False,  # Read as bytes first
            # encoding='utf-8' # Let's decode manually
        )
        stdout_bytes = result.stdout
        stderr_bytes = result.stderr
        
        stdout_str = ''
        stderr_str = ''

        try:
            stdout_str = stdout_bytes.decode('utf-8')
        except UnicodeDecodeError:
            try:
                stdout_str = stdout_bytes.decode('mbcs') # Fallback for Windows
            except Exception as e_stdout:
                stdout_str = f"Error decoding stdout: {e_stdout}"

        try:
            stderr_str = stderr_bytes.decode('utf-8')
        except UnicodeDecodeError:
            try:
                stderr_str = stderr_bytes.decode('mbcs') # Fallback for Windows
            except Exception as e_stderr:
                stderr_str = f"Error decoding stderr: {e_stderr}"

        return result.returncode == 0, stdout_str, stderr_str
    except Exception as e:
        return False, "", str(e)

def install_dependencies():
    """安装测试依赖"""
    print("📦 安装测试依赖...")
    
    dependencies = [
        'pytest>=7.0.0',
        'pytest-cov>=4.0.0',
        'pytest-mock>=3.10.0',
        'pytest-asyncio>=0.21.0',
        'pytest-timeout>=2.1.0',
        'pytest-xdist>=3.0.0',  # 并行测试
        'coverage>=7.0.0',
        'mock>=4.0.0'
    ]
    
    for dep in dependencies:
        print(f"  安装 {dep}...")
        success, stdout, stderr = run_command(f"pip install {dep}")
        if not success:
            print(f"  ❌ 安装 {dep} 失败: {stderr}")
            return False
        else:
            print(f"  ✅ {dep} 安装成功")
    
    return True

def run_tests(test_type='all', verbose=False, coverage=True, parallel=False):
    """运行测试"""
    print(f"🧪 运行测试 (类型: {test_type})...")
    
    # 基础命令
    cmd_parts = ['python', '-m', 'pytest']
    
    # 根据测试类型添加参数
    if test_type == 'unit':
        cmd_parts.extend(['-m', 'unit'])
    elif test_type == 'integration':
        cmd_parts.extend(['-m', 'integration'])
    elif test_type == 'api':
        cmd_parts.extend(['-m', 'api'])
    elif test_type == 'adapter':
        cmd_parts.extend(['-m', 'adapter'])
    elif test_type == 'database':
        cmd_parts.extend(['-m', 'database'])
    elif test_type == 'utils':
        cmd_parts.extend(['-m', 'utils'])
    elif test_type != 'all':
        # 运行特定测试文件
        cmd_parts.append(f"test/{test_type}")
    
    # 添加其他选项
    if verbose:
        cmd_parts.append('-v')
    
    if coverage:
        cmd_parts.extend(['--cov=.', '--cov-report=html', '--cov-report=term'])
    
    if parallel:
        cmd_parts.extend(['-n', 'auto'])
    
    # 运行测试
    command = ' '.join(cmd_parts)
    print(f"执行命令: {command}")
    
    success, stdout, stderr = run_command(command)
    
    if success:
        print("✅ 测试运行完成")
        print(stdout)
        return True
    else:
        print("❌ 测试运行失败")
        print(f"错误输出: {stderr}")
        if stdout:
            print(f"标准输出: {stdout}")
        return False

def generate_coverage_report():
    """生成覆盖率报告"""
    print("📊 生成覆盖率报告...")
    
    # 生成HTML报告
    success, stdout, stderr = run_command("coverage html")
    if success:
        print("✅ HTML覆盖率报告已生成: htmlcov/index.html")
    else:
        print(f"❌ HTML报告生成失败: {stderr}")
    
    # 生成XML报告
    success, stdout, stderr = run_command("coverage xml")
    if success:
        print("✅ XML覆盖率报告已生成: coverage.xml")
    else:
        print(f"❌ XML报告生成失败: {stderr}")
    
    # 显示覆盖率摘要
    success, stdout, stderr = run_command("coverage report")
    if success:
        print("📈 覆盖率摘要:")
        print(stdout)
    else:
        print(f"❌ 覆盖率摘要生成失败: {stderr}")

def clean_test_artifacts():
    """清理测试产物"""
    print("🧹 清理测试产物...")
    
    artifacts = [
        '.coverage',
        'coverage.xml',
        'htmlcov',
        '.pytest_cache',
        '__pycache__',
        '*.pyc',
        '*.pyo'
    ]
    
    for artifact in artifacts:
        if artifact.startswith('*'):
            # 使用find命令删除匹配的文件
            success, _, _ = run_command(f"find . -name '{artifact}' -delete")
        else:
            # 删除文件或目录
            if os.path.exists(artifact):
                if os.path.isdir(artifact):
                    success, _, _ = run_command(f"rm -rf {artifact}")
                else:
                    success, _, _ = run_command(f"rm -f {artifact}")
                
                if success:
                    print(f"  ✅ 已删除 {artifact}")
                else:
                    print(f"  ❌ 删除 {artifact} 失败")
    
    print("🧹 清理完成")

def main():
    """主函数"""
    parser = argparse.ArgumentParser(description='区块链中间件测试运行器')
    parser.add_argument(
        '--type', '-t',
        choices=['all', 'unit', 'integration', 'api', 'adapter', 'database', 'utils'],
        default='all',
        help='测试类型 (默认: all)'
    )
    parser.add_argument(
        '--install-deps', '-i',
        action='store_true',
        help='安装测试依赖'
    )
    parser.add_argument(
        '--verbose', '-v',
        action='store_true',
        help='详细输出'
    )
    parser.add_argument(
        '--no-coverage',
        action='store_true',
        help='禁用覆盖率报告'
    )
    parser.add_argument(
        '--parallel', '-p',
        action='store_true',
        help='并行运行测试'
    )
    parser.add_argument(
        '--clean', '-c',
        action='store_true',
        help='清理测试产物'
    )
    parser.add_argument(
        '--report', '-r',
        action='store_true',
        help='仅生成覆盖率报告'
    )
    
    args = parser.parse_args()
    
    # 确保在项目根目录
    project_root = Path(__file__).parent
    os.chdir(project_root)
    
    print("🚀 区块链中间件测试运行器")
    print(f"📁 工作目录: {project_root}")
    print("=" * 50)
    
    try:
        # 清理测试产物
        if args.clean:
            clean_test_artifacts()
            return
        
        # 仅生成报告
        if args.report:
            generate_coverage_report()
            return
        
        # 安装依赖
        if args.install_deps:
            if not install_dependencies():
                print("❌ 依赖安装失败")
                sys.exit(1)
        
        # 运行测试
        success = run_tests(
            test_type=args.type,
            verbose=args.verbose,
            coverage=not args.no_coverage,
            parallel=args.parallel
        )
        
        if not success:
            print("❌ 测试失败")
            sys.exit(1)
        
        # 生成覆盖率报告
        if not args.no_coverage:
            generate_coverage_report()
        
        print("\n🎉 所有测试完成!")
        
    except KeyboardInterrupt:
        print("\n⚠️  测试被用户中断")
        sys.exit(1)
    except Exception as e:
        print(f"\n❌ 运行测试时发生错误: {e}")
        sys.exit(1)

if __name__ == '__main__':
    main()